#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
Created on Jun 4, 2010

@author: pntruongan
'''
import math
import codecs

#import os

    
class Document:
    '''
    classdocs
    '''
    def __init__(self, docName):
        '''
        Constructor
        '''
        self.Vector = [] #Khởi tạo vector rỗng
        self.Name = docName;     
        pass
    
        
class DocumentCollection:
    StopWord = [u'của', u'thì', u'và', u'với', u'hay', u'hoặc', u'không', u'có', u'là', u'ngoài'
              u'lại', u'về', u'vào', u'ra', u'trước', u'sau', u'bị', u'được', u'tuy', u'thế', u'trong'      
              , u'nên', u'này', u'kia', u'nọ', u'đó', u'để', u'khiến', u'chứ', u'những', u'hơn'
              , u'đã', u'đang', u'sẽ', u'mà', u'tôi', u'nó', u'sắp', u'cô', u'ông', u'lắm', u'ta', u'do',
              u'nếu', u'tiếp', u'nữa', u'đến', u'đi', u'ấy', u'vẫn', u'cũng', u'nhưng', u'vì', u'vậy',
              u'các']
    def __init__(self, dic = None, stopword = None):
        self.GlobalVocabulary = [] #Một mảng hai chiều, lưu từ 
#        và số lần xuất hiện lớn nhất trong một văn bản của từ đó   
#        Ví dụ: GlobalVocabulary[0] = [ "em", "đi", "đâu", "về" ]
#               GlobalVocabulary[1] = [2    ,  5  ,  7   , 1    ]
#        Nghĩa là có một văn bản chứa 5 chữ đi. Và không văn bản nào chứa nhiều hơn.

        self.GlobalVocabulary.append([])
        self.GlobalVocabulary.append([])
        
        self.__DocList = [] #Mảng các đối tượng Document.
        
        
        try:
            self.__dic = {}
            dicFile = codecs.open( dic , encoding="utf-8" )
            a = u""
            a += dicFile.readline()
            while a != u'':
                a = a[:-1] #strip the last \n character

                self.__dic[a] = 1
                a = u"" + dicFile.readline()
        except :
            print ("No dictionary file found at" , dic)
            self.__dic = None
        
        try:
            self.__sw = {}
    
            #swFile = file( os.path.join(os.getcwdu() ,stopword) , "r" )
            swFile = codecs.open( stopword , encoding="utf-8" )
            a = u''
            a += swFile.readline()
            while a != u'':
                a = a[:-1] #strip the last \n character

                self.__sw[a] = 1
                a = u"" + swFile.readline()
        except:
            print ("No stopword list found at " , stopword)
            self.__sw = DocumentCollection.StopWord
        
            
    @staticmethod
    def isSpace(char):
        '''
        Nếu char là ký tự phân tách từ (dấu câu, dấu cách, v.v...)
        thì trả về true
        '''
        space = [u' ', u'.', u', u', u';', u':', u'!', u'?', u'\t', u'\n', u'(', u')', u'\r', u'”', u'“', u'\'', u'"',
                 '/', u'0', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'-', u'…',"%", u'=', u'+', u'*']
        
        return ( space.count( char) == 1 )
        
        
    def getDocListLen(self):
        return self.__DocList.__len__()
        
    def getDocumentVector(self, index):
        '''
        index là số thứ tự của văn bản trong __DocList
        '''        
        return self.__DocList[index].Vector[:]

    def getDocumentName(self, index):
        '''
        index là số thứ tự của văn bản trong __DocList
        '''        
        return self.__DocList[index].Name 

    @staticmethod
    def __termSpliter(string):
        i = 0
        result = []
        word = u""
        while i < len(string):
            #get a word
                          
            while i < len(string) and DocumentCollection.isSpace(string[i]):
                i += 1
            while  i < len(string) and not DocumentCollection.isSpace(string[i]) :
                word += string[i]
                i += 1            
            
            word = word.lower()
            
            result.append(word)
            
            word = u""
            i+=1
        return result
            
    def addTerm(self,word, currentDoc):
        
        if word in self.__sw:# self.__sw.has_key(word):
            return
            
        if word in self.GlobalVocabulary[0]:
            #We got an old word
            index = self.GlobalVocabulary[0].index(word)
            
            currentDoc.Vector[index] += 1
            #if (currentDoc.Vector[index] > self.GlobalVocabulary[1][index]):
            self.GlobalVocabulary[1][index] += 1
            
        else:
            #If the current word is not yet in the global vocabulary
            self.GlobalVocabulary[0].append(word)
            self.GlobalVocabulary[1].append(1)
            
            for doc in self.__DocList:
                #edit all existed vector
                doc.Vector.append(0)
            
            currentDoc.Vector.append(1)
                
    def addDoc(self, strDocName, strDoc):
        '''
        strDocName là tên văn bản để lần sau gọi lại còn có cái mà biết.
        strDoc là chuỗi văn bản cần thêm vào Tập văn bản
        '''
        currentDoc = Document(strDocName)
        currentDoc.Vector = [0] * len(self.GlobalVocabulary[0])
        word = u""
        i = 0
        
        terms = DocumentCollection.__termSpliter(strDoc)
         
        while i < len(terms):
            if self.__dic is not None:
                #Xét lần lượt từng cụm 4, 3, 2 rồi 1 tiếng xem có trong từ điển không
                k = min (len(terms) - i, 4)
                while k > 0:
                    word = u""
                    for j in range(k):
                        word += terms[i+j] + " "
                    word = word[:-1]#strip the last ' ' 
                    
                    if self.__dic.has_key(word): 
                        self.addTerm(word, currentDoc)
                        i += k - 1
                        break #break to prevent the follow if statemet re add the word
                    k -= 1
                if k == 0:
                    self.addTerm(terms[i], currentDoc)
            else:
                self.addTerm(terms[i], currentDoc)
            i += 1
            
        self.__DocList.append(currentDoc)
    
    def Addtfidf(self):
        #termDocCont[i] is the number of document contain term GlobalVocabulary[i]
        termDocCount = [0] * (len(self.GlobalVocabulary[0])) 
        for v in self.__DocList:
            for j in range(len( v.Vector)):
                if v.Vector[j] != 0:
                    termDocCount[j] += 1
                    
        for v in self.__DocList:
            sum_term = 0 #the number of occurrence of all term in document
            for j in v.Vector:
                sum_term += j
            
            for j in  range(len(v.Vector)):
                a = (v.Vector[j]/sum_term) * math.log( len(self.GlobalVocabulary[0]) / termDocCount[j])
                int(round(a*10000))
    
    def save(self, path):
        fi = open(path, "w")
        for i in self.GlobalVocabulary[0]:
            fi.write(i+ '\n')
        
        fi.write('--ENDTERMLIST--\n')
        
        for i in self.GlobalVocabulary[1]:
            fi.write(str(i) + ' ')
        fi.write('\n')
        
        for i in self.__DocList:
            fi.write(i.Name + "\n")
            for j in i.Vector:
                fi.write (str(j) + ' ')
            fi.write('\n')
        fi.close()
        
    def load(self,path):
        fi = file(path)
        
        #read vocabulary
        self.GlobalVocabulary[0] = []
        a = fi.readline()
        while a != '--ENDTERMLIST--\n':
            self.GlobalVocabulary[0].append(a)
            a = fi.readline()
        
        #read vocablary max appearance
        self.GlobalVocabulary[1] = []    
        a = fi.readline()
        for i in a.split(' ')[:-1]:
            self.GlobalVocabulary[1].append(int(i))
        
        self.__DocList = []
        a = fi.readline()
        
        while a != '':
            do = Document(a)
            a = fi.readline()
            for i in a.split(' ')[:-1]:
                do.Vector.append(int(i))
            self.__DocList.append(do)
            a = fi.readline()
        fi.close()
        
    def getTestDocVector(self, strDoc):
        '''
        Compute the Vecto represent that document. Since this document is a test
        we ignore all word that does not exist in GlobalVocabulary
        return the created document
        '''
        currentDoc = Document("###TEST###")
        currentDoc.Vector = [0] * len(self.GlobalVocabulary[0])
        word = u""
        i = 0
        
        while i < len(strDoc):
            #get a word
            while self.isSpace(strDoc[i]):
                i += 1
            while  i < len(strDoc) and not self.isSpace(strDoc[i]) :
                word += strDoc[i]
                i += 1            
            
            word = word.lower()
            
            try:
                #We got an old word
                index = self.GlobalVocabulary[0].index(word)
                
                currentDoc.Vector[index] += 1
            except ValueError:
                pass
                
            
            word = u""
            i += 1
        
        return currentDoc


